package org.jsoncrypto;

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

import junit.framework.TestCase;

import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.json.JSONException;
import org.json.JSONObject;
import org.jsoncrypto.util.Base64;
import org.junit.Test;

public class JWERSA1_5Test  extends TestCase {
	RSAPublicKey rsaPublicKey;
	RSAPrivateKey rsaPrivKey;
	private String thumbprint;

	public void setUp() throws NoSuchAlgorithmException, InvalidKeySpecException {
		
		final byte[] n = { (byte) 161, (byte) 248, (byte) 22, (byte) 10,
				(byte) 226, (byte) 227, (byte) 201, (byte) 180, (byte) 101,
				(byte) 206, (byte) 141, (byte) 45, (byte) 101, (byte) 98,
				(byte) 99, (byte) 54, (byte) 43, (byte) 146, (byte) 125,
				(byte) 190, (byte) 41, (byte) 225, (byte) 240, (byte) 36,
				(byte) 119, (byte) 252, (byte) 22, (byte) 37, (byte) 204,
				(byte) 144, (byte) 161, (byte) 54, (byte) 227, (byte) 139,
				(byte) 217, (byte) 52, (byte) 151, (byte) 197, (byte) 182,
				(byte) 234, (byte) 99, (byte) 221, (byte) 119, (byte) 17,
				(byte) 230, (byte) 124, (byte) 116, (byte) 41, (byte) 249,
				(byte) 86, (byte) 176, (byte) 251, (byte) 138, (byte) 143,
				(byte) 8, (byte) 154, (byte) 220, (byte) 75, (byte) 105,
				(byte) 137, (byte) 60, (byte) 193, (byte) 51, (byte) 63,
				(byte) 83, (byte) 237, (byte) 208, (byte) 25, (byte) 184,
				(byte) 119, (byte) 132, (byte) 37, (byte) 47, (byte) 236,
				(byte) 145, (byte) 79, (byte) 228, (byte) 133, (byte) 119,
				(byte) 105, (byte) 89, (byte) 75, (byte) 234, (byte) 66,
				(byte) 128, (byte) 211, (byte) 44, (byte) 15, (byte) 85,
				(byte) 191, (byte) 98, (byte) 148, (byte) 79, (byte) 19,
				(byte) 3, (byte) 150, (byte) 188, (byte) 110, (byte) 155,
				(byte) 223, (byte) 110, (byte) 189, (byte) 210, (byte) 189,
				(byte) 163, (byte) 103, (byte) 142, (byte) 236, (byte) 160,
				(byte) 198, (byte) 104, (byte) 247, (byte) 1, (byte) 179,
				(byte) 141, (byte) 191, (byte) 251, (byte) 56, (byte) 200,
				(byte) 52, (byte) 44, (byte) 226, (byte) 254, (byte) 109,
				(byte) 39, (byte) 250, (byte) 222, (byte) 74, (byte) 90,
				(byte) 72, (byte) 116, (byte) 151, (byte) 157, (byte) 212,
				(byte) 185, (byte) 207, (byte) 154, (byte) 222, (byte) 196,
				(byte) 199, (byte) 91, (byte) 5, (byte) 133, (byte) 44,
				(byte) 44, (byte) 15, (byte) 94, (byte) 248, (byte) 165,
				(byte) 193, (byte) 117, (byte) 3, (byte) 146, (byte) 249,
				(byte) 68, (byte) 232, (byte) 237, (byte) 100, (byte) 193,
				(byte) 16, (byte) 198, (byte) 182, (byte) 71, (byte) 96,
				(byte) 154, (byte) 164, (byte) 120, (byte) 58, (byte) 235,
				(byte) 156, (byte) 108, (byte) 154, (byte) 215, (byte) 85,
				(byte) 49, (byte) 48, (byte) 80, (byte) 99, (byte) 139,
				(byte) 131, (byte) 102, (byte) 92, (byte) 111, (byte) 111,
				(byte) 122, (byte) 130, (byte) 163, (byte) 150, (byte) 112,
				(byte) 42, (byte) 31, (byte) 100, (byte) 27, (byte) 130,
				(byte) 211, (byte) 235, (byte) 242, (byte) 57, (byte) 34,
				(byte) 25, (byte) 73, (byte) 31, (byte) 182, (byte) 134,
				(byte) 135, (byte) 44, (byte) 87, (byte) 22, (byte) 245,
				(byte) 10, (byte) 248, (byte) 53, (byte) 141, (byte) 154,
				(byte) 139, (byte) 157, (byte) 23, (byte) 195, (byte) 64,
				(byte) 114, (byte) 143, (byte) 127, (byte) 135, (byte) 216,
				(byte) 154, (byte) 24, (byte) 216, (byte) 252, (byte) 171,
				(byte) 103, (byte) 173, (byte) 132, (byte) 89, (byte) 12,
				(byte) 46, (byte) 207, (byte) 117, (byte) 147, (byte) 57,
				(byte) 54, (byte) 60, (byte) 7, (byte) 3, (byte) 77,
				(byte) 111, (byte) 96, (byte) 111, (byte) 158, (byte) 33,
				(byte) 224, (byte) 84, (byte) 86, (byte) 202, (byte) 229,
				(byte) 233, (byte) 161 };
		final byte[] e = { 1, 0, 1 };
		final byte[] d = { 18, (byte) 174, (byte) 113, (byte) 164,
				(byte) 105, (byte) 205, (byte) 10, (byte) 43, (byte) 195,
				(byte) 126, (byte) 82, (byte) 108, (byte) 69, (byte) 0,
				(byte) 87, (byte) 31, (byte) 29, (byte) 97, (byte) 117,
				(byte) 29, (byte) 100, (byte) 233, (byte) 73, (byte) 112,
				(byte) 123, (byte) 98, (byte) 89, (byte) 15, (byte) 157,
				(byte) 11, (byte) 165, (byte) 124, (byte) 150, (byte) 60,
				(byte) 64, (byte) 30, (byte) 63, (byte) 207, (byte) 47,
				(byte) 44, (byte) 211, (byte) 189, (byte) 236, (byte) 136,
				(byte) 229, (byte) 3, (byte) 191, (byte) 198, (byte) 67,
				(byte) 155, (byte) 11, (byte) 40, (byte) 200, (byte) 47,
				(byte) 125, (byte) 55, (byte) 151, (byte) 103, (byte) 31,
				(byte) 82, (byte) 19, (byte) 238, (byte) 216, (byte) 193,
				(byte) 90, (byte) 37, (byte) 216, (byte) 213, (byte) 206,
				(byte) 160, (byte) 2, (byte) 94, (byte) 227, (byte) 171,
				(byte) 46, (byte) 139, (byte) 127, (byte) 121, (byte) 33,
				(byte) 111, (byte) 198, (byte) 59, (byte) 234, (byte) 86,
				(byte) 39, (byte) 83, (byte) 180, (byte) 6, (byte) 68,
				(byte) 198, (byte) 161, (byte) 81, (byte) 39, (byte) 217,
				(byte) 178, (byte) 149, (byte) 69, (byte) 64, (byte) 160,
				(byte) 187, (byte) 225, (byte) 163, (byte) 5, (byte) 86,
				(byte) 152, (byte) 45, (byte) 78, (byte) 159, (byte) 222,
				(byte) 95, (byte) 100, (byte) 37, (byte) 241, (byte) 77,
				(byte) 75, (byte) 113, (byte) 52, (byte) 65, (byte) 181,
				(byte) 93, (byte) 199, (byte) 59, (byte) 155, (byte) 74,
				(byte) 237, (byte) 204, (byte) 146, (byte) 172, (byte) 227,
				(byte) 146, (byte) 126, (byte) 55, (byte) 245, (byte) 125,
				(byte) 12, (byte) 253, (byte) 94, (byte) 117, (byte) 129,
				(byte) 250, (byte) 81, (byte) 44, (byte) 143, (byte) 73,
				(byte) 97, (byte) 169, (byte) 235, (byte) 11, (byte) 128,
				(byte) 248, (byte) 168, (byte) 7, (byte) 70, (byte) 114,
				(byte) 138, (byte) 85, (byte) 255, (byte) 70, (byte) 71,
				(byte) 31, (byte) 52, (byte) 37, (byte) 6, (byte) 59,
				(byte) 157, (byte) 83, (byte) 100, (byte) 47, (byte) 94,
				(byte) 222, (byte) 30, (byte) 132, (byte) 214, (byte) 19,
				(byte) 8, (byte) 26, (byte) 250, (byte) 92, (byte) 34,
				(byte) 208, (byte) 81, (byte) 40, (byte) 91, (byte) 214,
				(byte) 59, (byte) 148, (byte) 59, (byte) 86, (byte) 93,
				(byte) 137, (byte) 138, (byte) 5, (byte) 104, (byte) 84,
				(byte) 19, (byte) 229, (byte) 60, (byte) 60, (byte) 108,
				(byte) 101, (byte) 37, (byte) 255, (byte) 31, (byte) 227,
				(byte) 78, (byte) 61, (byte) 220, (byte) 112, (byte) 240,
				(byte) 213, (byte) 100, (byte) 80, (byte) 253, (byte) 164,
				(byte) 139, (byte) 161, (byte) 46, (byte) 16, (byte) 78,
				(byte) 157, (byte) 235, (byte) 159, (byte) 184, (byte) 24,
				(byte) 129, (byte) 225, (byte) 196, (byte) 189, (byte) 242,
				(byte) 93, (byte) 146, (byte) 71, (byte) 244, (byte) 80,
				(byte) 200, (byte) 101, (byte) 146, (byte) 121, (byte) 104,
				(byte) 231, (byte) 115, (byte) 52, (byte) 244, (byte) 65,
				(byte) 79, (byte) 117, (byte) 167, (byte) 80, (byte) 225,
				(byte) 57, (byte) 84, (byte) 110, (byte) 58, (byte) 138,
				(byte) 115, (byte) 157 };

		BigInteger N = new BigInteger(1, n);
		BigInteger E = new BigInteger(1, e);
		BigInteger D = new BigInteger(1, d);

		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(N, E);
		RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(N, D);
		rsaPublicKey = (RSAPublicKey) keyFactory.generatePublic(pubKeySpec);
		rsaPrivKey = (RSAPrivateKey) keyFactory
				.generatePrivate(privKeySpec);
		Digest digest = new SHA256Digest();
		byte[] bytes = rsaPublicKey.getEncoded();
		digest.update(bytes, 0, bytes.length);
		byte[] out = new byte[digest.getDigestSize()];
		/* int result = */digest.doFinal(out, 0);
		thumbprint = Base64.encodeBytes(out,
				org.jsoncrypto.util.Base64.DONT_BREAK_LINES
						| org.jsoncrypto.util.Base64.URL);


	}

	@Test
  public void test() throws JcBaseException, JSONException {
    
    String rsa15AesGcm128HeaderStr = "{\"alg\":\"" + JcBase.KW_ALG_RSA1_5
        + "\",\r\n" + " \"enc\":\"" + JcBase.ENC_ALG_A128GCM
        + "\",\r\n" + " \"x5t\":\"" + thumbprint + "\"}";
    JSONObject header = new JSONObject(rsa15AesGcm128HeaderStr);
    JcLibEnc_AEAD enc = new JcEnc_A128GCM(header);
    JweRSA1_5 jwe = new JweRSA1_5(enc);
    String cleartext = "text";
    byte[] contentBytes = cleartext.getBytes();
    byte[] bytes = new byte[16];
    SecureRandom sr = new SecureRandom();
    sr.nextBytes(bytes);
    String encodedJweIvSegment = Base64.encodeBytes(bytes, Base64.URL);
    String jweStr = jwe.encrypt(contentBytes, rsaPublicKey, encodedJweIvSegment );
    
    
    JweRSA1_5 receiverJwe = new JweRSA1_5(jweStr);
    byte[] receiverContentBytes = receiverJwe.decrypt(rsaPrivKey);
    String receiverText = new String(receiverContentBytes);
    assertEquals(cleartext, receiverText);
  }

  public void testRubbishAlg() throws JcBaseException, JSONException {
    
    String rsa15AesGcm128HeaderStr = "{\"alg\":\"" + "rubbish"
        + "\",\r\n" + " \"enc\":\"" + JcBase.ENC_ALG_A128GCM
        + "\",\r\n" + " \"x5t\":\"" + thumbprint + "\"}";
    JSONObject header = new JSONObject(rsa15AesGcm128HeaderStr);
    JcLibEnc_AEAD enc = new JcEnc_A128GCM(header);
    try {
      new JweRSA1_5(enc);
      fail("The alg is wrong and we should never reach this statement");
    } catch (JcBaseException e) {}
  }

  public void testOptionalAlg() throws JcBaseException, JSONException {
    
    String rsa15AesGcm128HeaderStr = "{\"enc\":\"" + JcBase.ENC_ALG_A128GCM + "\"}";
    JSONObject header = new JSONObject(rsa15AesGcm128HeaderStr);
    JcLibEnc_AEAD enc = new JcEnc_A128GCM(header);
    JweRSA1_5 jwe = new JweRSA1_5(enc);
    String cleartext = "text";
    byte[] contentBytes = cleartext.getBytes();
    byte[] bytes = new byte[16];
    SecureRandom sr = new SecureRandom();
    sr.nextBytes(bytes);
    String encodedJweIvSegment = Base64.encodeBytes(bytes, Base64.URL);
    String jweStr = jwe.encrypt(contentBytes, rsaPublicKey, encodedJweIvSegment );
    
    
    JweRSA1_5 receiverJwe = new JweRSA1_5(jweStr);
    byte[] receiverContentBytes = receiverJwe.decrypt(rsaPrivKey);
    String receiverText = new String(receiverContentBytes);
    assertEquals(cleartext, receiverText);
  }

}
